/**
 * Audio Module - Audio playback and management system
 * 
 * Features:
 * - Audio playback with WAV files - Support for standard WAV audio format
 * - Audio streaming playback - Real-time audio stream processing
 * - Text-to-speech playback - TTS functionality for text conversion
 * - Volume control and range management - Precise volume control with range validation
 * - Playback interruption and cache management - Advanced playback control and resource management
 * 
 * Usage:
 * - Audio playback service - Background music, sound effects, notifications
 * - TTS service - Voice announcements, accessibility features (not all devices support)
 * - Volume management - System-wide volume control with user-friendly interface
 * - Support cross-thread audio playback
 * - The WAV format should be Channels : 1, Sample Rate : approximately 24000, Precision : 16-bit, other formats need to be converted to this format
 */
import { audioClass } from './libvbar-m-dxaudio.so'

// Create audio object instance for native operations
const audioObj = new audioClass();
// Export audio module interface
const audio = {}

// Playback status code constants
audio.PLAY_CODE = {
	SUCCESS: 0,        // Playback completed successfully
	FAILED: -1,        // Playback operation failed
	QUEUE_IS_FULL: -2  // Playback queue is full, cannot add more audio
}

// Language type constants for TTS functionality
audio.PLAY_TYPE = {
	CHINESE_DATA: 0,     /** Chinese language TTS data */
	ENGLISH_DATA: 1,     /** English language TTS data */
}

/**
 * Audio system initialization
 * @param {number} [volume=5] Volume level (0-10) - User-friendly volume range (0 means mute), default 5
 * @param {number} [periodSize=512] Period size in samples - Audio processing granularity, default 512
 * @param {number} [bufferSize=2048] Buffer size in samples - Audio buffer capacity, default 2048
 * @throws {Error} If initialization fails - Throws error when audio system cannot be initialized
 * 
 * Technical Details:
 * - periodSize: Controls audio processing latency. Smaller values (256,512) provide lower latency 
 *   but higher CPU usage. Larger values (1024,2048) reduce CPU usage but increase latency.
 * - bufferSize: Determines audio smoothness. Smaller values (1024,2048) use less memory but may 
 *   cause audio stuttering. Larger values (4096,8192) provide smoother playback but use more memory.
 * - Recommended configurations:
 *   * Low latency: (256, 1024) - For real-time communication
 *   * High quality: (1024, 4096) - For music playback
 *   * Balanced: (512, 2048) - For general applications
 */
audio.init = function (volume = 5, periodSize = 512, bufferSize = 2048) {
	// Parameter validation
	validateNumber(volume, 'volume');
	validateNumber(periodSize, 'periodSize');
	validateNumber(bufferSize, 'bufferSize');

	// Validate volume range (0-10 for user-friendly interface; 0 means mute)
	if (volume < 0 || volume > 10) {
		throw new Error("audio.init: 'volume' must be between 0 and 10");
	}

	// Initialize audio system with specified parameters
	audioObj.audioInit(volume, periodSize, bufferSize)
}

/**
 * Audio system deinitialization
 * @returns {boolean} true if deinitialization successful, false otherwise
 * 
 * Note: This function releases all audio resources and should be called
 * when the audio system is no longer needed to prevent resource leaks.
 */
audio.deinit = function () {
	return audioObj.audioDeinit()
}

/**
 * Validate if the specified volume level is within acceptable range
 * @param {number} volume Volume level (0-10), required parameter (0 means mute)
 * @returns {boolean} true if volume is valid, false otherwise
 * 
 * This function checks if the volume level is within the supported range
 * before attempting to set it, preventing invalid volume operations.
 */
audio.isValidVolume = function (volume) {
	if (volume == undefined || volume == null) {
		throw new Error("audio.isValidVolume: 'volume' parameter should not be null")
	}
	if (volume < 0 || volume > 10) {
		throw new Error("audio.isValidVolume: 'volume' must be between 0 and 10")
	}
	return audioObj.audioIsValidVolume(volume)
}

/**
 * Get current audio volume level
 * @returns {number} Current volume level (0-10) - Mapped from hardware volume to user-friendly range (0 means mute)
 * 
 * The returned value is automatically mapped from the hardware volume range
 * to the user-friendly 1-10 range for consistent interface experience.
 */
audio.getVolume = function () {
	return audioObj.audioGetVolume()
}

/**
 * Set audio volume level
 * @param {number} volume Volume level (0-10), required parameter (0 means mute)
 * @returns {boolean} true if volume set successfully, false otherwise
 * 
 * Volume levels outside the valid range (1-10) will be automatically clamped
 * to the nearest valid value. The function maps user volume to hardware volume
 * internally for optimal audio quality.
 */
audio.setVolume = function (volume) {
	if (volume == undefined || volume == null) {
		throw new Error("audio.setVolume: 'volume' parameter should not be null")
	}
	if (volume < 0 || volume > 10) {
		throw new Error("audio.setVolume: 'volume' must be between 0 and 10")
	}
	return audioObj.audioSetVolume(volume)
}

/**
 * Play WAV audio file from file path
 * @param {string} path Absolute path to WAV file, required parameter
 * @returns {number} Playback status code (see audio.PLAY_CODE constants)
 * 
 * File path should start with '/app/code/' and typically placed in the project's
 * resource directory (same level as src directory). Supports standard WAV format.
 * 
 * Return values:
 * - 0: Playback started successfully
 * - -1: Playback failed
 * - -2: Playback queue is full
 */
audio.play = function (path) {
	if (!path) {
		throw new Error("audio.play: 'path' parameter should not be null")
	}
	return audioObj.audioPlayWav(path)
}

/**
 * Play audio from ArrayBuffer data (streaming audio)
 * @param {ArrayBuffer} buffer Audio data buffer, required parameter
 * @returns {number} Playback status code (see audio.PLAY_CODE constants)
 * 
 * This function is useful for playing audio streams, real-time audio data,
 * or audio data received from network sources. The buffer should contain
 * valid WAV format audio data.
 */
audio.playWavData = function (buffer) {
	if (!buffer) {
		throw new Error("audio.playWavData: 'buffer' parameter should not be null")
	}
	return audioObj.audioPlayWavData(buffer)
}

/**
 * Play text using Text-to-Speech (TTS) functionality
 * @param {string} txt Text to be converted to speech, required parameter
 * @param {number} type Language type, required parameter (0: Chinese, 1: English)
 * @returns {number} Playback status code (see audio.PLAY_CODE constants)
 * 
 * TTS functionality may not be supported on all devices. The function converts
 * the provided text to speech in the specified language and plays it through
 * the audio system.
 * 
 * Language types:
 * - 0: Chinese
 * - 1: English
 */
audio.playTxt = function (txt, type) {
	if (!txt) {
		throw new Error("audio.playTxt: 'txt' parameter should not be null")
	}
	if (typeof type !== 'number' || isNaN(type)) {
		throw new Error("audio.playTxt: 'type' parameter should not be null")
	}
	return audioObj.audioPlayTxt(txt, type)
}

/**
 * Interrupt currently playing audio
 * @returns {boolean} true if interruption successful, false otherwise
 * 
 * This function immediately stops the currently playing audio without affecting
 * the playback queue. It's useful for emergency stops or when switching
 * between different audio sources.
 */
audio.interrupt = function () {
	return audioObj.audioPlayingInterrupt()
}

/**
 * Clear audio playback cache and queue
 * @returns {boolean} true if cache cleared successfully, false otherwise
 * 
 * This function removes all pending audio from the playback queue and clears
 * the audio cache. It should be used when you want to completely reset the
 * audio playback state or free up memory resources.
 * 
 * Note: This operation is mutually exclusive with playback functions and
 * should not be called while audio is actively playing.
 */
audio.clearCache = function () {
	return audioObj.audioClearPlayCache()
}


function validateNumber(value, name) {
	if (typeof value !== 'number' || isNaN(value)) {
		throw new TypeError(`${name} must be a valid number`);
	}
}

// Export audio module as default export
export default audio;